package xyz.xiangyushui.subtitleConverter;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.function.BiFunction;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SubtitleEditor {
	private File file;

	public SubtitleEditor(String pathFileSrc) {
		this.file = new File(pathFileSrc);
	}

	/*
	 * 字幕提前
	 */
	public void early(int second) {
		doBasic(second,(t,s)->decrease(t,s));
	}

	/*
	 * 字幕延迟
	 */
	public void delay(int second) {
         doBasic(second,(t,s)->increase(t,s));
	}
	/**
	 * first read file and then write file according to seconds you want to early or delay 
	 * @param second
	 * @param f
	 */
	
	private void doBasic(int second,BiFunction<String,Integer,String> f){
		BufferedReader br = null;
		StringBuffer bf=new StringBuffer();
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(
					file)));
			String line ;
			while ((line = br.readLine())!= null) {
				String[] timePoints = getTimePoints(line);
				if (!timePoints[0].equals("")) {
					for (String timePoint : timePoints) {
						String newTimePoint = f.apply(timePoint, second);
						line = line.replace(timePoint, newTimePoint);
					}
				}
				bf.append(line);
				bf.append(System.getProperty("line.separator"));
			}
			write(bf.toString());
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					br = null;
				}
			}
		}
	}

	private String decrease(String timePoint, int secondToDecrease) {
		String newTimePoint = "";
		String hour = timePoint.substring(0, 2);
		String minute = timePoint.substring(3, 5);
		String second = timePoint.substring(6, 8);
		int secondInt = toInteger(second);
		int minuteInt = toInteger(minute);
		int hourInt = toInteger(hour);
		if (secondInt >= secondToDecrease) {
			newTimePoint = hour + ":" + minute + ":"
					+ format2digit(secondInt - secondToDecrease);
		} else {
			if (hourInt * 3600 + minuteInt * 60 + secondInt >= secondToDecrease) {
				int hourToDec = secondToDecrease / 3600;
				int minuteToDec = secondToDecrease % 3600 / 60;
				int secondToDec = secondToDecrease - 3600 * hourToDec - 60
						* minuteToDec;
				int minuteFlag = secondInt - secondToDec >= 0 ? 0 : 1;
				minuteToDec += minuteFlag;
				int hourFlag = minuteInt - minuteToDec >= 0 ? 0 : 1;
				newTimePoint = format2digit(hourInt - hourToDec - hourFlag)
						+ ":"
						+ format2digit(minuteInt - minuteToDec >= 0 ? minuteInt
								- minuteToDec : 60 + minuteInt - minuteToDec)
						+ ":"
						+ format2digit(secondInt - secondToDec >= 0 ? secondInt
								- secondToDec : 60 + secondInt - secondToDec);
			} else {
				newTimePoint = timePoint;
			}
		}
		return newTimePoint;
	}

	private String increase(String timePoint, int secondToIncrease) {
		String newTimePoint = "";
		String hour = timePoint.substring(0, 2);
		String minute = timePoint.substring(3, 5);
		String second = timePoint.substring(6, 8);
		int secondInt = toInteger(second);
		int minuteInt = toInteger(minute);
		int hourInt = toInteger(hour);
		int hourToInc = secondToIncrease / 3600;
		int minuteToInc = secondToIncrease % 3600 / 60;
		int secondToInc = secondToIncrease - 3600 * hourToInc - 60
				* minuteToInc;
		int minuteFlag = secondInt + secondToInc >= 60 ? 1 : 0;
		minuteToInc += minuteFlag;
		int hourFlag = minuteInt + minuteToInc >= 60 ? 1 : 0;
		hourToInc += hourFlag;
		newTimePoint = format2digit(hourInt + hourToInc)
				+ ":"
				+ format2digit(minuteInt + minuteToInc >= 60 ? minuteInt
						+ minuteToInc - 60 : minuteInt + minuteToInc)
				+ ":"
				+ format2digit(secondInt + secondToInc >= 60 ? secondInt
						+ secondToInc - 60 : secondInt + secondToInc);
		return newTimePoint;
	}

	private void write(String content) {
		BufferedWriter bw = null;
		try {
			bw = new BufferedWriter(new FileWriter(file));
			bw.write(content);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			// 关闭流
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					bw = null;
				}
			}
		}
	}

	private int toInteger(String s) {
		return Integer.parseInt(s);
	}

	private String format2digit(int a) {
		return String.format("%02d", a);
	}

	private String[] getTimePoints(String line) {
		String[] timePoints = { "", "" };
		Pattern p = Pattern.compile("\\d{2}:\\d{2}:\\d{2}");
		Matcher m = p.matcher(line);
		int i = 0;
		while (m.find()) {
			timePoints[i] = m.group();
			i++;
		}
		return timePoints;
	}
	private static void usage(){
		System.err.println("usage:java SubtitleEditor early/delay seconds pathSrcFile");
		System.exit(-1);
	}

	public static void main(String[] args) {
		if(args.length!=3){
			usage();
		}
		int second=0;
		try{
			second=Integer.parseInt(args[1]);
		}catch(NumberFormatException e){
			usage();
		}
		SubtitleEditor se=new SubtitleEditor(args[2]);
		switch (args[0]){
			case "early":se.early(second);break;
			case "delay":se.delay(second);break;
			default:usage();
		}		
	}
}
